package eu.robico.simulator.simulatorinterface.actionpanel.objects;

import java.awt.Color;
import java.awt.Graphics2D;

import eu.robico.simulator.simulatorinterface.MainController;
import eu.robico.simulator.simulatorinterface.actionpanel.Position;
import eu.robico.simulator.simulatorinterface.communication.Protocol.Trigger;
import eu.robico.simulator.simulatorinterface.utils.Boundary;

public class CollisionSensor implements RobotComponent 
{
	public enum CollisionSensorPosition
	{
		FRONT,
		BACK
	}
	/**
	 * Represents a on-screen collision sensor object
	 * @author A.J. Janssen
	 * @version 0.1
	 *
	 */
	private class CollisionSensorObject
	{
		public void paint(Graphics2D graphics) 
		{
			Color sensorColor = (onLane) ? Color.red : Color.cyan;
			graphics.setColor(sensorColor);
			graphics.fillRect((int) x - (width / 2), (int) y - (height / 2), width, height);
		}
	}
	
	private CollisionSensorObject collisionSensorObject;
	private Robot robot;
	private CollisionSensorPosition collisionSensorPosition;
	private Position centerPosition;
	private int height = 66, width = 4;
	private double x, y, rotation, distanceToRobotCenter;
	private boolean onLane = false;
	
	public CollisionSensor(Robot robot, Position location, double rotation, CollisionSensorPosition collisionSensorPosition)
	{
		this.robot = robot;
		this.x = location.x;
		this.y = location.y;
		this.rotation = rotation;
		this.collisionSensorPosition = collisionSensorPosition;
		collisionSensorObject = this.new CollisionSensorObject();
	}
	
	private boolean detectsCollision(ObstacleObject obstacle)
	{
		//Check if collision sensor intersects with obstacle
		//Get boundaries
		Boundary sensorBounds = Boundary.getRotatedRectangleBounds(centerPosition, rotation, width, height);
		Boundary obstacleBounds = Boundary.getRectangleBounds(obstacle.getPosition(), obstacle.getWidth());
		//Check for collisions
		return sensorBounds.colidesWith(obstacleBounds);
	}
	
	//RobotComponent implementation below
	
	@Override
	public void update()
	{
		for (ActionPanelObject object : robot.getActionPanel().getObjects())
			if (object instanceof ObstacleObject && detectsCollision((ObstacleObject) object))
			{
				if (!onLane) //just detected a new collision
				{
					//Send toggle trigger
					Trigger trigger = (collisionSensorPosition == CollisionSensorPosition.FRONT) ?
							Trigger.COLLISIONFRONTTOGGLE : Trigger.COLLISIONBACKTOGGLE;
					MainController.getInstance().sendTrigger(trigger);
					onLane = true;
				}
				return;
			}
		//No collisions detected
		if (onLane)
		{
			//Send toggle trigger
			Trigger trigger = (collisionSensorPosition == CollisionSensorPosition.FRONT) ?
					Trigger.COLLISIONFRONTTOGGLE : Trigger.COLLISIONBACKTOGGLE;
			MainController.getInstance().sendTrigger(trigger);
			onLane = false;
		}
	}
	
	@Override
	public void paint(Graphics2D graphics) 
	{
		collisionSensorObject.paint(graphics);
	}

	@Override
	public double getRotation() 
	{
		return rotation;
	}

	@Override
	public void setRotation(double rotation) 
	{
		this.rotation = rotation;
	}

	@Override
	public void setTrueCenter(Position centerPoint) 
	{
		this.centerPosition = centerPoint;
	}

	@Override
	public Position getTrueCenter() 
	{
		return centerPosition;
	}

	@Override
	public double getX() 
	{
		return x;
	}

	@Override
	public double getY() 
	{
		return y;
	}

	@Override
	public void setX(double x) 
	{
		this.x = x;
	}

	@Override
	public void setY(double y) 
	{
		this.y = y;
	}

	@Override
	public RobotComponentType getType() 
	{
		return RobotComponentType.CollisionSensor;
	}

	@Override
	public Position getPosition() 
	{
		return new Position(x, y);
	}

	@Override
	public double getDistanceToRobotCenter() 
	{
		return distanceToRobotCenter;
	}

	@Override
	public void setDistanceToRobotCenter(double distanceToRobotCenter) 
	{
		this.distanceToRobotCenter = distanceToRobotCenter;
	}
}
